/**
 * @date 2006-2-7 9:08:03
 *
 */
package org.nanhill.commons.lang;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @author alin
 * 
 */
public class ReflectCache {

	private static final Map<String, Type[]> methodParamTypeCache = new HashMap<String, Type[]>();

	private static final Map<String, Method> firstPublicMethodCache = new HashMap<String, Method>();

	public static Method getFirstPublicMethod(Class clz, String methodName)
			throws NoSuchMethodException {
		String key = getKey(clz, methodName);
		if (!firstPublicMethodCache.containsKey(key)) {
			Method method = ReflectKit.getOnePublicMethod(clz, methodName);
			firstPublicMethodCache.put(key, method);
		}
		return firstPublicMethodCache.get(key);

	}

	/**
	 * e.g: if method is method(int[], List<String>), the return Type[] is
	 * {class int[], List<String>}, the first type is class, second is a
	 * parameterizedType.
	 * 
	 * @return
	 */
	public static Type[] getMethodParamTypeFocusClass(Method method) {
		String key = getKey(method);
		if (!methodParamTypeCache.containsKey(key)) {
			cacheMethodParamTypeFocusClass(key, method);
		}
		return methodParamTypeCache.get(key);
	}

	private static void cacheMethodParamTypeFocusClass(String key, Method method) {
		Type[] paramTypes = method.getGenericParameterTypes();
		Class[] paramClzs = method.getParameterTypes();
		for (int i = 0; i < paramTypes.length; i++) {
			Class clz = paramTypes[i].getClass();
			if (ReflectKit.isDefaultGenericArrayType(clz)) {
				paramTypes[i] = paramClzs[i];
			}
		}
		methodParamTypeCache.put(key, paramTypes);
	}

	private static String getKey(Method method) {
		return method.toGenericString();
	}

	private static String getKey(Class clz, String methodName) {
		return clz.getName() + ":" + methodName;
	}

}
